import os
from datetime import datetime, timedelta
from flask import (
    render_template,
    request,
    flash,
    redirect,
    url_for,
    jsonify,
    g,
    send_from_directory,
    Blueprint,
)
from models import app, User, Jobnumber, Category, Subcategory, Task, db, Holiday
from sqlalchemy.sql import func, extract
from flask_login import (
    LoginManager,
    login_required,
    login_user,
    logout_user,
    current_user,
)
from flask_wtf import FlaskForm
from functools import wraps
from bp_admin import bp_admin
import json

bp_user = Blueprint("bp_user", __name__)


@bp_user.route("/", methods=["GET"])
@login_required
def index():
    jobnumbers = (
        db.session.query(Jobnumber.id, Jobnumber.name, Jobnumber.desc)
        .filter_by(delete=False)
        .all()
    )
    categories = (
        db.session.query(Category.id, Category.name).filter_by(delete=False).all()
    )
    subcategories = (
        db.session.query(
            Subcategory.id, Subcategory.name, Subcategory.categoryid, Category.name
        )
        .filter_by(delete=False)
        .join(Category, Category.id == Subcategory.categoryid)
        .all()
    )
    holidaysArray = (
        db.session.query(Holiday.date, Holiday.desc, Holiday.isworkday)
        .filter_by(delete=False)
        .all()
    )
    holidaysOffset = {}
    holidays = {}
    for holiday in holidaysArray:
        date = holiday[0].strftime("%Y-%m-%d")
        if holiday[2]:
            holidaysOffset[date] = holiday[1]
        else:
            holidays[date] = holiday[1]

    # 算法有点傻 待优化
    optgroup = {}
    for i in subcategories:
        cat = i[3]
        j = optgroup.get(cat)
        if j:
            j.append(i)
            tmp = {cat: j}
        else:
            tmp = {cat: [i]}
        optgroup.update(tmp)
    return render_template(
        "index.html",
        categories=categories,
        jobnumbers=jobnumbers,
        subcategories=subcategories,
        optgroup=optgroup,
        holidays=json.dumps(holidays),
        holidaysOffset=json.dumps(holidaysOffset),
    )


@bp_user.route("/logout")
def logout():
    logout_user()
    return redirect(url_for("login"), code=302)


# subcategory routes....
@bp_user.route("/subcategories", methods=["GET"])
@login_required
def subcategories():
    # subcategories = db.session.query(Subcategory.id, Subcategory.name, Subcategory.color, Subcategory.categoryid, Subcategory.delete).all()
    subcategories = (
        db.session.query(
            Subcategory.id,
            Subcategory.name,
            Category.color,
            Subcategory.categoryid,
            Subcategory.delete,
            Category.name,
        )
        .join(Category, Subcategory.categoryid == Category.id)
        .filter(Subcategory.delete == False)
        .order_by(Category.id)
        .all()
    )
    return render_template("subcategories.html", subcategories=subcategories)


@bp_user.route("/setting", methods=["GET", "POST"])
@login_required
def setting():
    if request.method == "GET":
        return render_template("setting.html")
    if request.method == "POST":
        oldpassword = request.form.get("oldpassword").strip()
        password = request.form.get("password").strip()

        if not current_user.check_password(oldpassword):
            flash("旧密码错误", category="danger")
            return redirect(url_for("bp_user.setting"), code=302)

        if not password:
            flash("新密码不能为空", category="danger")
            return redirect(url_for("bp_user.setting"), code=302)
        current_user.password = password
        db.session.commit()
        flash("密码更新成功!", category="success")
        return redirect(url_for("bp_user.setting"), code=302)


@bp_user.route("/ajaxs/events")
@login_required
def get_user_events():
    userid = current_user.id
    start = request.args.get("start")
    end = request.args.get("end")
    tasks = (
        db.session.query(
            Task.id,
            Task.title,
            Task.remark,
            Task.userid,
            Task.categoryid,
            Task.subcategoryid,
            Task.jobnumberid,
            Task.manhour,
            Task.tasktime,
            Task.createtime,
            Task.edittime,
            Task.delete,
            User.name,
            Category.name,
            Category.color,
            Subcategory.name,
            Subcategory.color,
            Jobnumber.name,
        )
        .filter_by(userid=userid)
        .filter_by(delete=False)
        .filter(Task.tasktime <= end)
        .filter(Task.tasktime >= start)
        .join(Jobnumber, Jobnumber.id == Task.jobnumberid)
        .join(User, User.id == Task.userid)
        .join(Category, Category.id == Task.categoryid)
        .join(Subcategory, Subcategory.id == Task.subcategoryid)
        .all()
    )
    data = []
    for task in tasks:
        data.append(
            {
                "id": task.id,
                "title": task.title,
                "jobnumberid": task.jobnumberid,
                "remark": task.remark,
                "manhour": task.manhour,
                "categoryid": task.categoryid,
                "subcategoryid": task.subcategoryid,
                "start": task.tasktime.strftime("%Y-%m-%d"),
                "color": "#{}".format(task[14]),
            }
        )
        # print(task)
    return jsonify(data)


@bp_user.route("/ajaxs/count")
@login_required
def get_user_day_count():
    userid = current_user.id
    start = request.args.get("start")
    end = request.args.get("end")
    tasks = (
        db.session.query(Task.tasktime, func.sum(Task.manhour).label("total"))
        .filter(Task.userid == userid)
        .filter(Task.delete == False)
        .filter(Task.tasktime < end)
        .filter(Task.tasktime >= start)
        .filter(Task.categoryid != 33)
        .group_by(Task.tasktime)
        .all()
    )
    vacations = (
        db.session.query(
            Task.subcategoryid, Subcategory.name, func.sum(Task.manhour).label("total")
        )
        .join(Subcategory, Subcategory.id == Task.subcategoryid)
        .filter(Task.userid == userid)
        .filter(Task.delete == False)
        .filter(Task.tasktime < end)
        .filter(Task.tasktime >= start)
        .filter(Task.categoryid == 33)
        .group_by(Task.subcategoryid)
        .all()
    )
    data = {}
    for task in tasks:
        d = task.tasktime.strftime("%Y-%m-%d")
        h = "%.1f" % task.total
        data[d] = h

    vacation = {}
    for v in vacations:
        _, a, b = v
        vacation[a] = b

    return jsonify({"task": data, "vacation": vacation})


# task routes....
@bp_user.route("/tasks", methods=["GET"])
@login_required
def tasks():
    # tasks = db.session.query(Task.id, Task.name, Task.color, Task.categoryid, Task.delete).all()
    tasks = (
        db.session.query(
            Task.id,
            Task.title,
            Task.remark,
            Task.userid,
            Task.categoryid,
            Task.subcategoryid,
            Task.jobnumberid,
            Task.manhour,
            Task.tasktime,
            Task.createtime,
            Task.edittime,
            Task.delete,
            User.name,
            Category.name,
            Subcategory.name,
            Jobnumber.name,
        )
        .filter_by(userid=current_user.id)
        .filter_by(delete=False)
        .join(Jobnumber, Jobnumber.id == Task.jobnumberid)
        .join(User, User.id == Task.userid)
        .join(Category, Category.id == Task.categoryid)
        .join(Subcategory, Subcategory.id == Task.subcategoryid)
        .all()
    )
    # print(tasks[0],dir(tasks[0]),tasks[0]._fields)
    # we can valuate task[0].userid
    # But we can valuate task[0].user_name because it has username jobnumber name and they all call name
    # print(tasks.statement)
    # for attr in dir(tasks):
    #     print(attr, eval('tasks.{}'.format(attr)))
    flash("支持模糊搜索:空格 *。如 搜索2月份包含AD的事件: 2019-02-* AD ", category="info")
    flash("也支持正则搜索 如 搜索非休假事件 ^((?!休假).)*$ ", category="success")
    return render_template("tasks.html", tasks=tasks)


@bp_user.route("/task", methods=["GET", "POST"])
@login_required
def task_create():
    if request.method == "GET":
        jobnumbers = (
            db.session.query(Jobnumber.id, Jobnumber.name).filter_by(delete=False).all()
        )
        categories = (
            db.session.query(Category.id, Category.name).filter_by(delete=False).all()
        )
        subcategories = (
            db.session.query(
                Subcategory.id, Subcategory.name, Subcategory.categoryid, Category.name
            )
            .filter_by(delete=False)
            .join(Category, Category.id == Subcategory.categoryid)
            .all()
        )
        # 算法有点傻 待优化
        optgroup = {}
        for i in subcategories:
            cat = i[3]
            j = optgroup.get(cat)
            if j:
                j.append(i)
                tmp = {cat: j}
            else:
                tmp = {cat: [i]}
            optgroup.update(tmp)
        return render_template(
            "task_create.html",
            categories=categories,
            jobnumbers=jobnumbers,
            subcategories=subcategories,
            optgroup=optgroup,
        )
    if request.method == "POST":
        userid = current_user.id
        jobnumberid = request.form.get("jobnumberid")
        categoryid = request.form.get("categoryid")
        subcategoryid = request.form.get("subcategoryid")
        tasktime = request.form.get("tasktime")
        manhour = request.form.get("manhour")
        title = request.form.get("title")
        remark = request.form.get("remark")

        if not jobnumberid:
            flash("工作令号不能为空", category="danger")
            return redirect(url_for("bp_user.task_create"), code=302)
        jobnumberid = jobnumberid.strip()
        if not categoryid:
            flash("大类不能为空", category="danger")
            return redirect(url_for("bp_user.task_create"), code=302)
        categoryid = int(categoryid)
        if not subcategoryid:
            flash("分类不能为空", category="danger")
            return redirect(url_for("bp_user.task_create"), code=302)
        subcategoryid = int(subcategoryid)
        if not tasktime:
            flash("任务日期不能为空", category="danger")
            return redirect(url_for("bp_user.task_create"), code=302)
        tasktime = datetime.strptime(tasktime, "%m/%d/%Y")
        if not title:
            flash("任务不能为空", category="danger")
            return redirect(url_for("bp_user.task_create"), code=302)
        if not manhour:
            flash("工时不能为空", category="danger")
            return redirect(url_for("bp_user.task_create"), code=302)
        try:
            manhour = float(manhour)
        except:
            flash("工时必须是数字", category="danger")
            return redirect(url_for("bp_user.task_create"), code=302)

        if not remark:
            remark = ""

        task = Task(
            title=title,
            remark=remark,
            userid=userid,
            categoryid=categoryid,
            subcategoryid=subcategoryid,
            jobnumberid=jobnumberid,
            manhour=manhour,
            tasktime=tasktime,
            createtime=datetime.now(),
        )
        db.session.add(task)
        db.session.commit()
        flash("任务创建成功。", category="success")
        return redirect(url_for("bp_user.tasks"), code=302)


@bp_user.route("/task/<taskid>", methods=["GET", "POST"])
@login_required
def task_edit(taskid):
    if request.method == "GET":
        task = (
            db.session.query(
                Task.id,
                Task.jobnumberid,
                Task.categoryid,
                Task.subcategoryid,
                Task.tasktime,
                Task.manhour,
                Task.title,
                Task.remark,
            )
            .filter_by(id=taskid)
            .first()
        )
        if task:
            jobnumbers = (
                db.session.query(Jobnumber.id, Jobnumber.name, Jobnumber.desc)
                .filter_by(delete=False)
                .all()
            )
            categories = (
                db.session.query(Category.id, Category.name)
                .filter_by(delete=False)
                .all()
            )
            subcategories = (
                db.session.query(
                    Subcategory.id,
                    Subcategory.name,
                    Subcategory.categoryid,
                    Category.name,
                )
                .filter_by(delete=False)
                .join(Category, Category.id == Subcategory.categoryid)
                .all()
            )
            # 算法有点傻 待优化
            optgroup = {}
            for i in subcategories:
                cat = i[3]
                j = optgroup.get(cat)
                if j:
                    j.append(i)
                    tmp = {cat: j}
                else:
                    tmp = {cat: [i]}
                optgroup.update(tmp)
            return render_template(
                "task_edit.html",
                task=task,
                categories=categories,
                jobnumbers=jobnumbers,
                subcategories=subcategories,
                optgroup=optgroup,
            )
        else:
            flash("任务不存在!", category="danger")
            return redirect(url_for("bp_user.tasks"), code=302)

    if request.method == "POST":
        jobnumberid = request.form.get("jobnumberid")
        categoryid = request.form.get("categoryid")
        subcategoryid = request.form.get("subcategoryid")
        tasktime = request.form.get("tasktime")
        manhour = request.form.get("manhour")
        title = request.form.get("title")
        remark = request.form.get("remark")

        if not jobnumberid:
            flash("工作令号不能为空", category="danger")
            return redirect(url_for("bp_user.task_edit", taskid=taskid), code=302)
        jobnumberid = jobnumberid.strip()
        if not categoryid:
            flash("大类不能为空", category="danger")
            return redirect(url_for("bp_user.task_edit", taskid=taskid), code=302)
        categoryid = int(categoryid)
        if not subcategoryid:
            flash("分类不能为空", category="danger")
            return redirect(url_for("bp_user.task_edit", taskid=taskid), code=302)
        subcategoryid = int(subcategoryid)
        if not tasktime:
            flash("任务日期不能为空", category="danger")
            return redirect(url_for("bp_user.task_edit", taskid=taskid), code=302)
        tasktime = datetime.strptime(tasktime, "%m/%d/%Y")
        if not title:
            flash("任务不能为空", category="danger")
            return redirect(url_for("bp_user.task_edit", taskid=taskid), code=302)
        if not manhour:
            flash("工时不能为空", category="danger")
            return redirect(url_for("bp_user.task_edit", taskid=taskid), code=302)
        try:
            manhour = float(manhour)
        except:
            flash("工时必须是数字", category="danger")
            return redirect(url_for("bp_user.task_edit", taskid=taskid), code=302)

        if not remark:
            remark = ""

        task = Task.query.filter_by(id=taskid).first()
        task.title = title
        task.remark = remark
        task.categoryid = categoryid
        task.subcategoryid = subcategoryid
        task.jobnumberid = jobnumberid
        task.manhour = manhour
        task.tasktime = tasktime
        task.edittime = datetime.now()

        db.session.commit()
        flash("修改成功。", category="success")
        return redirect(url_for("bp_user.tasks", taskid=taskid), code=302)


@bp_user.route("/task/<taskid>/delete")
@login_required
def task_delete(taskid):
    task = Task.query.filter_by(id=taskid).first()
    if not task:
        flash("分类不存在", category="danger")
        return redirect(url_for("bp_user.tasks"), code=302)
    task.delete = not task.delete
    task.edittime = datetime.now()
    db.session.commit()
    flash("修改成功。", category="success")
    return redirect(url_for("bp_user.tasks"), code=302)


if __name__ == "__main__":

    pass
